﻿using System;
using System.IO;
using System.Xml;
using Microsoft.SharePoint;
using Microsoft.SharePoint.Utilities;

namespace SPSource2010.Lists
{
    public class ListTemplateManifestGenerator
    {
        private XmlDocument docElementManifestsXmlDoc;

        public ListTemplateManifestGenerator()
        {
            docElementManifestsXmlDoc = new XmlDocument();
            XmlNode elementManifestsNode = docElementManifestsXmlDoc.CreateElement("Elements");

            XmlAttribute nameSpaceAttr = docElementManifestsXmlDoc.CreateAttribute("xmlns");
            nameSpaceAttr.Value = Constants.SharePointXmlNamespace;
            elementManifestsNode.Attributes.Append(nameSpaceAttr);

            docElementManifestsXmlDoc.AppendChild(elementManifestsNode);
        }

        /// <summary>
        /// http://msdn.microsoft.com/en-us/library/ms439434.aspx
        /// </summary>
        /// <param name="listName"></param>
        /// <param name="webUrl"></param>
        public void CreateListTemplateNode(string listName, string webUrl, int listTemplateType)
        {
            using (SPSite site = new SPSite(webUrl))
            {
                using (SPWeb web = site.OpenWeb())
                {
                    SPList list = web.Lists[listName];
                    XmlNode listTemplateNode = docElementManifestsXmlDoc.CreateElement("ListTemplate");

                    // (optional)AllowDeletion = "TRUE" | "FALSE"
                    XmlAttribute allowDeletionAttribute = docElementManifestsXmlDoc.CreateAttribute("AllowDeletion");
                    allowDeletionAttribute.Value = list.AllowDeletion.ToString();
                    listTemplateNode.Attributes.Append(allowDeletionAttribute);

                    // (optional)AllowEveryoneViewItems = "TRUE" | "FALSE"
                    XmlAttribute allowEveryoneViewItemsAttribute = docElementManifestsXmlDoc.CreateAttribute("AllowEveryoneViewItems");
                    allowEveryoneViewItemsAttribute.Value = list.AllowEveryoneViewItems.ToString();
                    listTemplateNode.Attributes.Append(allowEveryoneViewItemsAttribute);

                    //  BaseType = "0" | "1" |"3" | "4" | "5"
                    XmlAttribute baseTypeAttr = docElementManifestsXmlDoc.CreateAttribute("BaseType");
                    baseTypeAttr.Value = ListEnumHelpers.ReturnBaseType(list);
                    listTemplateNode.Attributes.Append(baseTypeAttr);

                    //  DisplayName = "Text"
                    XmlAttribute displayNameAttr = docElementManifestsXmlDoc.CreateAttribute("DisplayName");
                    displayNameAttr.Value = listName;
                    listTemplateNode.Attributes.Append(displayNameAttr);

                    // (optional)Description = "Text"
                    XmlAttribute descriptionAttr = docElementManifestsXmlDoc.CreateAttribute("Description");
                    descriptionAttr.Value = list.Description;
                    listTemplateNode.Attributes.Append(descriptionAttr);

                    // (optional)EnableModeration = "TRUE" | "FALSE"
                    XmlAttribute enableModerationAttr = docElementManifestsXmlDoc.CreateAttribute("EnableModeration");
                    enableModerationAttr.Value = list.EnableModeration.ToString();
                    listTemplateNode.Attributes.Append(enableModerationAttr);

                    // (optional)Hidden = "TRUE" | "FALSE"
                    XmlAttribute hiddenAttribute = docElementManifestsXmlDoc.CreateAttribute("Hidden");
                    hiddenAttribute.Value = list.Hidden.ToString();
                    listTemplateNode.Attributes.Append(hiddenAttribute);

                    // (optional)OnQuickLaunch = "TRUE" | "FALSE"
                    XmlAttribute onQuickLaunchAttribute = docElementManifestsXmlDoc.CreateAttribute("OnQuickLaunch");
                    onQuickLaunchAttribute.Value = list.OnQuickLaunch.ToString();
                    listTemplateNode.Attributes.Append(onQuickLaunchAttribute);

                    //  Name = "Text"
                    XmlAttribute nameAttr = docElementManifestsXmlDoc.CreateAttribute("Name");
                    nameAttr.Value = SPStringUtility.RemoveNonAlphaNumericChars(listName);
                    listTemplateNode.Attributes.Append(nameAttr);

                    //  (optional)Type = "Integer"
                    XmlAttribute typeAttr = docElementManifestsXmlDoc.CreateAttribute("Type");
                    //NOTE: if picture library needs to be 109!
                    if (list.BaseTemplate == SPListTemplateType.PictureLibrary)
                    {
                        typeAttr.Value = "109";
                    }
                    else
                    {
                        typeAttr.Value = listTemplateType.ToString();
                    }
                    listTemplateNode.Attributes.Append(typeAttr);

                    //  (optional)SecurityBits = "Text"
                    XmlAttribute securityBitsAttr = docElementManifestsXmlDoc.CreateAttribute("SecurityBits");
                    securityBitsAttr.Value = "11"; //TODO: get this
                    listTemplateNode.Attributes.Append(securityBitsAttr);

                    // TODO: (optional)Sequence = "Integer"
                    XmlAttribute sequenceAttr = docElementManifestsXmlDoc.CreateAttribute("Sequence");
                    sequenceAttr.Value = "110"; //TODO: get this - 410 for custom list,210 for picture library
                    listTemplateNode.Attributes.Append(sequenceAttr);

                    // TODO: (optional)DocumentTemplate = "Integer"
                    XmlAttribute documentTemplateAttribute = docElementManifestsXmlDoc.CreateAttribute("DocumentTemplate");
                    documentTemplateAttribute.Value = GetDocumentTemplate(list);
                    listTemplateNode.Attributes.Append(documentTemplateAttribute);

                    // (optional)VersioningEnabled = "TRUE" | "FALSE">
                    XmlAttribute versioningEnabledAttribute = docElementManifestsXmlDoc.CreateAttribute("VersioningEnabled");
                    versioningEnabledAttribute.Value = list.EnableVersioning.ToString();
                    listTemplateNode.Attributes.Append(versioningEnabledAttribute);
                    
                    // TODO: (optional)AlwaysIncludeContent = "TRUE" | "FALSE"
                    // TODO: (optional)CacheSchema = "TRUE" | "FALSE"
                    // TODO: (optional)Catalog = "TRUE" | "FALSE"
                    // TODO: (optional)Category = "Libraries" | "Communications" | "Tracking" | "Custom Lists"
                    // TODO: (optional)Default = "TRUE" | "FALSE"
                    // TODO: (optional)DisableAttachments = "TRUE" | "FALSE"
                    // TODO: (optional)DisallowContentTypes = "TRUE" | "FALSE"
                    // TODO: (optional)DontSaveInTemplate = "TRUE" | "FALSE"
                    // TODO: (optional)EditPage = "Text"
                    // TODO: (optional)FeatureId = "Text"
                    // TODO: (optional)FolderCreation = "TRUE" | "FALSE"
                    // TODO: (optional)HiddenList = "TRUE" | "FALSE"
                    // TODO: (optional)Image = "URL" - 'Image="/_layouts/images/itil.gif"' for picture library
                    // TODO: (optional)MultipleMtgDataList = "TRUE" | "FALSE"
                    // TODO: (optional)MustSaveRootFiles = "TRUE" | "FALSE"
                    // TODO: (optional)NewPage = "Text"
                    // TODO: (optional)NoCrawl = "TRUE" | "FALSE"
                    // TODO: (optional)Path = "Text"
                    // TODO: (optional)RootWebOnly = "TRUE" | "FALSE"
                    // TODO: (optional)SetupPath = "Text"
                    // TODO: (optional)SyncType = "Text"
                    // TODO: (optional)Unique = "TRUE" | "FALSE"
                    // TODO: (optional)UseRootFolderForNavigation = "TRUE" | "FALSE"
                    
                    XmlNode elementManifestsNode = docElementManifestsXmlDoc.SelectSingleNode("Elements");
                    elementManifestsNode.AppendChild(listTemplateNode);
                }
            }
        }

        private string GetDocumentTemplate(SPList list)
        {
            return "101";//TODO: apparently obfuscated - 'DocumentTemplate="100"' for picture library
        }

        /// <summary>
        /// http://msdn.microsoft.com/en-us/library/ms476062.aspx
        /// </summary>
        /// <param name="listName"></param>
        /// <param name="webUrl"></param>
        public void CreateListInstanceNode(string listName, string webUrl, int listTemplateType, Guid featureId)
        {
            using (SPSite site = new SPSite(webUrl))
            {
                using (SPWeb web = site.OpenWeb())
                {
                    SPList list = web.Lists[listName];
                    XmlNode listInstanceNode = docElementManifestsXmlDoc.CreateElement("ListInstance");

                    XmlAttribute featureIdAttr = docElementManifestsXmlDoc.CreateAttribute("FeatureId");
                    featureIdAttr.Value = featureId.ToString();
                    listInstanceNode.Attributes.Append(featureIdAttr);

                    XmlAttribute idAttr = docElementManifestsXmlDoc.CreateAttribute("Id");
                    idAttr.Value = Guid.NewGuid().ToString();
                    listInstanceNode.Attributes.Append(idAttr);

                    XmlAttribute templateTypeAttr = docElementManifestsXmlDoc.CreateAttribute("TemplateType");
                    //NOTE: if picture library needs to be 109!
                    if (list.BaseTemplate == SPListTemplateType.PictureLibrary)
                    {
                        templateTypeAttr.Value = "109";
                    }
                    else
                    {
                        templateTypeAttr.Value = listTemplateType.ToString();
                    }
                    listInstanceNode.Attributes.Append(templateTypeAttr);

                    XmlAttribute titleAttr = docElementManifestsXmlDoc.CreateAttribute("Title");
                    titleAttr.Value = listName;
                    listInstanceNode.Attributes.Append(titleAttr);

                    XmlAttribute urlAttr = docElementManifestsXmlDoc.CreateAttribute("Url");
                    urlAttr.Value = String.Format("Lists/{0}", listName);
                    listInstanceNode.Attributes.Append(urlAttr);

                    //TODO: (optional) Description = "Text"
                    //TODO: (optional) OnQuickLaunch = "TRUE" | "FALSE"
                    //TODO: (optional) QuickLaunchUrl = "Text"
                    //TODO: (optional) RootWebOnly = "TRUE" | "FALSE"

                    XmlNode elementManifestsNode = docElementManifestsXmlDoc.SelectSingleNode("Elements");
                    elementManifestsNode.AppendChild(listInstanceNode);
                }
            }
        }

        public FileInfo SaveListManifest(DirectoryInfo directory, string spSourceFileName)
        {
            string elementManifestFilePath = directory.FullName + "\\" + spSourceFileName.Replace(Constants.SPSourceExtension, "") + "_manifest.xml";
            docElementManifestsXmlDoc.Save(elementManifestFilePath);
            return new FileInfo(elementManifestFilePath);
        }
    }
}
